package com.chapter17.demo5;


/**
 * 为了保护对共享资源的访问，Java给出了一个synchronized关键字，
 *
 * 当使用了同步语句块后，线程访问被保护的代码会频繁地对对象进行加锁和解锁，所以会有一定的性能损耗；
 * 没有获得锁的线程只能等待，这也会影响并发执行的效率。所以，同步语句块的范围不要设置太大，应该只包含最关键的需要保护的资源访问代码。
 */
public class SellTicketTask implements Runnable{
   private int tickets =100;
   //用作锁对象：
   //  synObject可以是任意的对象。在Java中，每个对象都有一个关联的监视器（monitor），或者叫作锁，
   //  当一个线程访问同步语句块时，首先要锁定对象的监视器（或者叫作获得锁），
   //  之后当另一个线程访问该语句块时，发现对象的监视器已被锁定，那么就会等待。
   //  当同步语句块执行完毕后，拥有锁的线程就会解锁监视器，于是另一个线程就可以锁定对象的监视器，进而访问同步语句块中的代码。
   // private Object obj = new Object();

    @Override
    public void run() {
        while (true){
            synchronized (this){
                if(tickets>0){
                    System.out.printf("%s sell tickets: %d%n",Thread.currentThread().getName(),tickets);
                    tickets --;
                }else {
                    break;
                }
            }
        }

    }
}
